﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Text.RegularExpressions;
using CalculatorLogic;
using CalculatorLogic.Algebraic_Math;

namespace CalculatorGUI
{
    public partial class CalcControl : UserControl
    {
        // Constructor
        public CalcControl()
        {
            InitializeComponent();
            textBox1.Text = "";
        }

        EquationParser parser = new EquationParser();
        PostfixSolver solver = new PostfixSolver();
        Solve algebraSolver = new Solve();
        Factor factorSolver = new Factor();
        Expand expandSolver = new Expand();
        Zeros zerosSolver = new Zeros();
        Equation equation = new Equation();
        TokenHelper tokenHelper = new TokenHelper();

        #region Numbers
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "1";
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "2";
        }

        private void button3_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "3";
        }

        private void button5_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "4";
        }

        private void button6_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "5";
        }

        private void button7_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "6";
        }

        private void button9_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "7";
        }

        private void button10_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "8";
        }

        private void button11_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "9";
        }

        private void button13_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "0";
        }
        #endregion Numbers

        #region Symbols        
        private void button14_Click(object sender, RoutedEventArgs e)
        {
            if (textBox1.Text == string.Empty)
            {
                textBox1.Text += "0.";
            }
            else
            {
                if (textBox1.Text[textBox1.Text.Length - 1] == ' ' ||
                    textBox1.Text[textBox1.Text.Length - 1] == '-' ||
                    textBox1.Text[textBox1.Text.Length - 1] == '\r')
                {
                    textBox1.Text += "0.";
                }
                if (tokenHelper.IsNumber(textBox1.Text[textBox1.Text.Length - 1].ToString()))
                {
                    textBox1.Text += ".";
                }
            }
        }

        private void button15_Click(object sender, RoutedEventArgs e)
        {
            if (textBox1.Text == string.Empty)
            {
                textBox1.Text += "-";
            }
            else
            {
                if (!tokenHelper.IsNumber(textBox1.Text[textBox1.Text.Length - 1].ToString()) &&
                    textBox1.Text[textBox1.Text.Length - 1].ToString() != "π" &&
                    textBox1.Text[textBox1.Text.Length - 1].ToString() != "e" &&
                    textBox1.Text[textBox1.Text.Length - 1].ToString() != "x")
                {
                    textBox1.Text += "-";
                }
            }
        }

        private void button28_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "( ";
        }

        private void button29_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += " )";
        }

        private void button22_Click(object sender, RoutedEventArgs e)
        {
            addBasicMath(" ^ ");
        }

        private void button23_Click(object sender, RoutedEventArgs e)
        {
            addBasicMath(" = ");
        }

        private void button30_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "x";
        }

        private void button36_Click_1(object sender, RoutedEventArgs e)
        {
            textBox1.Text += 'π';
        }

        private void button37_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += 'e';
        }

        //ANS key
        private void button38_Click(object sender, RoutedEventArgs e)
        {
            if (equation.LastAnswers.Count != 0)
            {
                string temp = equation.LastAnswers[equation.LastAnswers.Count-1];
                textBox1.Text += temp;
            }
            else
            {
                textBox1.Text += "";
            }
        }

        #endregion Symbols

        #region Basic Math
        
        /// <summary>
        /// Add a basic math (+-*/^) operator to the text box
        /// </summary>
        /// <param name="_operator">the type of operator to add</param>
        private void addBasicMath(string _operator)
        {
            if (textBox1.Text != string.Empty &&
                textBox1.Text[textBox1.Text.Length-1] != '-')
            {
                //Tests if last character is an operator (to avoid multiple operators in a row syntax error)
                if (!tokenHelper.IsOperator(textBox1.Text.TrimEnd(' ')[textBox1.Text.TrimEnd(' ').Length - 1].ToString()))
                {
                    //If last line is empty, gets last ANS
                    if (GetLastLine(textBox1.Text) == "")
                    {
                        textBox1.Text += equation.LastAnswers[equation.LastAnswers.Count - 1] + _operator;
                    }
                    else
                    {
                        textBox1.Text += _operator;
                    }
                }
                //If last character IS an operator, it is replaced with the new operator
                else
                {
                    textBox1.Text = textBox1.Text.TrimEnd(' ');
                    textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1, 1);
                    textBox1.Text = textBox1.Text.TrimEnd(' ');
                    textBox1.Text += _operator;
                }
            }
        }

        private void button8_Click(object sender, RoutedEventArgs e)
        {
            addBasicMath(" + ");
        }

        private void button12_Click(object sender, RoutedEventArgs e)
        {
            addBasicMath(" - ");
        }

        private void button16_Click(object sender, RoutedEventArgs e)
        {
            addBasicMath(" * ");
        }

        private void button20_Click(object sender, RoutedEventArgs e)
        {
            addBasicMath(" / ");
        }
        #endregion Basic Math

        #region Trig
        private void button17_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "SIN ( ";
        }

        private void button18_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "COS ( ";
        }

        private void button19_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "TAN ( ";
        }

        private void button33_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "CSC ( ";
        }

        private void button34_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "COT ( ";
        }

        private void button35_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "SEC ( ";
        }
        #endregion Trig

        #region Logarithmic Functions
        private void button21_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "LOG ( ";
        }

        private void button27_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text += "LN ( ";
        }
        #endregion Logarithmic Functions

        #region Calculator Functions
        private void button32_Click(object sender, RoutedEventArgs e)
        {
            textBox1.Text = string.Empty;
        }

        private void button31_Click(object sender, RoutedEventArgs e)
        {
            
            textBox1.Text = textBox1.Text.TrimEnd(' ');

            if (textBox1.Text != string.Empty)
            {
                if (GetLastLine(textBox1.Text) == "")
                {
                    List<string> lines = textBox1.Text.Split('\r').ToList();
                    lines.RemoveRange(lines.Count - 3, 3);
                    textBox1.Text = string.Empty;
                    foreach (string line in lines)
                    {
                        textBox1.Text += line + '\r';
                    }
                }
                else
                {
                    try
                    {
                        if (tokenHelper.IsRightAssociative(textBox1.Text.Substring(textBox1.Text.Length - 4, 2)))
                        {
                            if (textBox1.Text.Substring(textBox1.Text.Length - 4, 2) == "LN")
                            {
                                textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 4);
                            }
                            else
                            {
                                textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 5);
                            }
                        }
                        else
                        {
                            textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);
                        }
                    }
                    catch
                    {
                        textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);
                    }
                }
            }

            if (textBox1.Text != string.Empty)
            {
                if (tokenHelper.IsNumber(textBox1.Text.TrimEnd(' ')[textBox1.Text.TrimEnd(' ').Length - 1].ToString()))
                {
                    textBox1.Text = textBox1.Text.TrimEnd(' ');
                }
            }
        }

        private void button4_Click(object sender, RoutedEventArgs e)
        {
            if (GetLastLine(textBox1.Text).Contains("="))
            {
                if (GetLastLine(textBox1.Text) != "")
                {
                    equation.Input[0] = GetLastLine(textBox1.Text).Replace(" ", "");
                    if (Regex.IsMatch(equation.Input[0], @"(\d+)?x[+-]\d+=(\d+)?x[+-]\d+|(\d+)?x[+-]\d+=\d+$|(\d+)?x=\d+$"))
                    {
                        algebraSolver.Apply(equation);
                        textBox1.Text += "\r";
                        textBox1.Text += equation.Solved.PadLeft(28);
                        textBox1.Text += "\r";
                    }
                    else
                    {
                        MessageBox.Show("Not in correct format." + "\n" + " Format: ie. 2x+4=12x+3, x+2=12 or 12x=36");
                    }
                }
                else
                {
                    equation.Input[0] = equation.LastAnswers[equation.LastAnswers.Count-1];
                    if (Regex.IsMatch(equation.Input[0], @"(\d+)?x[+-]\d+=(\d+)?x[+-]\d+|(\d+)?x[+-]\d+=\d+$|(\d+)?x=\d+$"))
                    {
                        algebraSolver.Apply(equation);
                        textBox1.Text += " = \r";
                        textBox1.Text += equation.Solved.PadLeft(28);
                        textBox1.Text += "\r";
                    }
                    else
                    {
                        MessageBox.Show("Not in correct format." + "\n" + " Format: ie. 2x+4=12x+3, x+2=12 or 12x=36");
                    }
                }
            }
            else
            {
                if (!GetLastLine(textBox1.Text).Contains('x'))
                {
                    string answer = Solve(GetLastLine(textBox1.Text));
                    textBox1.Text += " = \r";
                    textBox1.Text += answer.PadLeft(28);
                    textBox1.Text += "\r";
                }
                else
                {
                    MessageBox.Show("Please remove the x from the formula");
                }
            }
            autoScroll();
        }
        #endregion Calculator Functions

        #region Algebraic Functions
        private void button24_Click(object sender, RoutedEventArgs e)
        {
            if (GetLastLine(textBox1.Text) != "")
            {
                equation.Input[0] = GetLastLine(textBox1.Text).Replace(" ", "");
                if (Regex.IsMatch(equation.Input[0], @"(\d+\()?(\d+)?\*?x\^2[+-](\d+)?\*?x[+-]\d+"))
                {
                    factorSolver.Apply(equation);
                    textBox1.Text += " = \r";
                    textBox1.Text += equation.Solved;
                    textBox1.Text += "\r";

                    equation.LastAnswers.Add(equation.Solved);
                    autoScroll();
                }
                else
                {
                    MessageBox.Show("Not in correct format." + "\n" + " Format: ie. x^2+x+1");
                }
            }
            else
            {
                equation.Input[0] = equation.LastAnswers[equation.LastAnswers.Count-1];
                if (Regex.IsMatch(equation.Input[0], @"(\d+\()?(\d+)?\*?x\^2[+-](\d+)?\*?x[+-]\d+"))
                {
                    factorSolver.Apply(equation);
                    textBox1.Text += " = \r";
                    textBox1.Text += equation.Solved;
                    textBox1.Text += "\r";

                    equation.LastAnswers.Add(equation.Solved);
                    autoScroll();
                }
                else
                {
                    MessageBox.Show("Not in correct format." + "\n" + " Format: ie. x^2+x+1");
                }
            }
        }

        private void button25_Click(object sender, RoutedEventArgs e)
        {
            string expand = GetLastLine(textBox1.Text);
            if (expand != "")
            {
                expand = expand.Replace(" ", "");
                expand = expand.Replace("+", " + ");
                equation.Input[0] = expand.Trim();
                if (Regex.IsMatch(equation.Input[0], @"\(x\s?[+-]\s?\d+\)\^2|\(x\s?[+-]\s?\d+\)\(x\s?[+-]\s?\d+\)"))
                {
                    expandSolver.Apply(equation);
                    textBox1.Text += " = \r";
                    textBox1.Text += equation.Solved;
                    textBox1.Text += "\r";

                    equation.LastAnswers.Add(equation.Solved);
                    autoScroll();
                }
                else
                {
                    MessageBox.Show("Not in correct format." + "\n" + " Format: ie. (x+3)^2 or (x+3)(x-3)");
                }
            }
            else
            {
                equation.Input[0] = equation.LastAnswers[equation.LastAnswers.Count-1];
                if (Regex.IsMatch(equation.Input[0], @"\(x\s?[+-]\s?\d+\)\^2|\(x\s?[+-]\s?\d+\)\(x\s?[+-]\s?\d+\)"))
                {
                    expandSolver.Apply(equation);
                    textBox1.Text += " = \r";
                    textBox1.Text += equation.Solved;
                    textBox1.Text += "\r";

                    equation.LastAnswers.Add(equation.Solved);
                    autoScroll();
                }
                else
                {
                    MessageBox.Show("Not in correct format." + "\n" + " Format: ie. (x+3)^2 or (x+3)(x-3)");
                }
            }
        }

        private void button26_Click(object sender, RoutedEventArgs e)
        {
            if (GetLastLine(textBox1.Text) != "")
            {
                equation.Input[0] = GetLastLine(textBox1.Text).Replace(" ", "");
                if (Regex.IsMatch(equation.Input[0], @"(\d+\()?(\d+)?\*?x\^2[+-](\d+)?\*?x[+-]\d+"))
                {
                    zerosSolver.Apply(equation);
                    textBox1.Text += " = \r";
                    textBox1.Text += equation.Solved;
                    textBox1.Text += "\r";

                    autoScroll();
                }
                else
                {
                    MessageBox.Show("Not in correct format." + "\n" + " Format: ie. x^2+x+1");
                }
            }
            else
            {
                equation.Input[0] = equation.LastAnswers[equation.LastAnswers.Count - 1];
                if (Regex.IsMatch(equation.Input[0], @"(\d+\()?(\d+)?\*?x\^2[+-](\d+)?\*?x[+-]\d+"))
                {
                    zerosSolver.Apply(equation);
                    textBox1.Text += " = \r";
                    textBox1.Text += equation.Solved;
                    textBox1.Text += "\r";

                    autoScroll();
                }
                else
                {
                    MessageBox.Show("Not in correct format." + "\n" + " Format: ie. x^2+x+1");
                }
            }
        }
        #endregion Algebraic Functions

        #region Methods
        public string Solve(string input)
        {
            string temp = parser.Parse(input);
            string answer = solver.Solve(temp, equation);
            return answer;
        }

        public string GetLastLine(string text)
        {
            string[] lines = Regex.Split(textBox1.Text, "\r");
            return lines.Last();
        }

        public string GetPreviousLine(string text)
        {
            try
            {
                string[] lines = Regex.Split(textBox1.Text, "\r");
                return lines[lines.Length - 2];
            }
            catch
            {
                return "#";
            }
        }

        /// <summary>
        /// Scrolls the textbox automatically as the height increases
        /// </summary>
        private void autoScroll()
        {
            if (textBox1.ActualHeight > scrollViewer1.ViewportHeight)
            {
                scrollViewer1.ScrollToVerticalOffset(scrollViewer1.ScrollableHeight + textBox1.ActualHeight);
            }
        }

        
        

        

        //private void graphingGUI()
        //{
        //    if (graphing)
        //    {
        //        scrollViewer1.Visibility = Visibility.Collapsed;
        //        graphControl1.Visibility = Visibility.Visible;
        //    }
        //    else
        //    {
        //        scrollViewer1.Visibility = Visibility.Visible;
        //        graphControl1.Visibility = Visibility.Collapsed;
        //    }
        //}
        #endregion Methods
    }
}
